package ui;

import static javax.swing.JOptionPane.ERROR_MESSAGE;
import static javax.swing.JOptionPane.showMessageDialog;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;

import preprocess.XMLDoc;
import preprocess.XmlTransfer;
import similarity.MixSimilarity;
import similarity.Similarity;
import similarity.SimpleTEDSimilarity;
import similarity.TextSimilarity;
import ui.clustering.ClusteringGraph;
import ui.clustering.VisClusteringInfo;
import utils.Configuration;
import utils.ResourceCritical;
import classification.calcSimilarity.CalcSimilarityBySLVM;
import clustering.streamming.StreammingKMedianClustering;

public class CluVisualFrame extends JInternalFrame
{
    private static final long                  serialVersionUID      = 1L;
    private static HashMap<String, Similarity> similarityMap;
    private static ArrayList<String>           similarityList;
    private static String                      ROOT_PATH;
    private static String                      TED;
    private static String                      VSM;
    private static String                      SLVM;
    private static String                      MIX;
    private JDialog                            controlComponent      = null;
    private JLabel                             ClusterCountLabel     = null;
    private JTextField                         ClusterCountTextField = null;
    private JLabel                             clusterSizeLabel      = null;
    private JTextField                         blockSizeTextField    = null;
    private JLabel                             similarityLabel       = null;
    private JComboBox                          similarityComboBox    = null;
    private JButton                            startButton           = null;
    private JButton                            finishButton          = null;
    private ResourceCritical<XMLDoc>           critical              = null;
    private JPanel                             clusterPanel          = null;
    private JButton                            settingButton         = null;
    private boolean                            isFinish              = false;

    private JButton getSettingButton()
    {
        if (settingButton == null)
        {
            settingButton = new JButton("打开聚类设置窗口");
            settingButton.addActionListener(new ActionListener()
            {
                @Override
                public void actionPerformed(ActionEvent e)
                {
                    getControlComponent().setVisible(true);
                }
            });
        }
        return settingButton;
    }

    static
    {
        similarityMap = new HashMap<String, Similarity>();
        ROOT_PATH = Configuration.RootPath;
        TED = "\u6811\u7f16\u8f91\u8ddd\u79bb";
        VSM = "\u5411\u91cf\u7a7a\u95f4\u6a21\u578b";
        MIX = "\u6df7\u5408\u76f8\u4f3c\u5ea6\u6a21\u578b";
        SLVM = "SLVM";
        similarityList = new ArrayList<String>();
        try
        {
            similarityMap.put(TED, new SimpleTEDSimilarity());
            similarityList.add(MIX);
            similarityMap.put(VSM, new TextSimilarity());
            similarityList.add(TED);
            similarityMap.put(MIX, new MixSimilarity());
            similarityList.add(VSM);
            similarityMap.put(SLVM, new CalcSimilarityBySLVM());
            similarityList.add(SLVM);
        }
        catch (Exception e)
        {}
    }

    /**
     * This is the default constructor
     */
    public CluVisualFrame()
    {
        super("XML流聚类窗口", true, false, true, true);
        initialize();
    }

    /**
     * This method initializes this
     * 
     * @return void
     */
    private void initialize()
    {
        this.setSize(700, 700);
        setLayout(new BorderLayout());
        // this.add(getControlPanel(), null); // Generated
        this.add(getClusterPanel(), BorderLayout.CENTER); // Generated
        this.add(getSettingButton(), BorderLayout.SOUTH);
        setCritical(new ResourceCritical<XMLDoc>(1000));
        setVisible(true);
    }

    public void run(StreammingKMedianClustering clu)
    {
        isFinish = false;
        Timer timer = new Timer();
        timer.schedule(new VisualizationTask(clu), 5000, 10000);
    }

    class VisualizationTask extends TimerTask
    {
        StreammingKMedianClustering clu;

        public VisualizationTask(StreammingKMedianClustering clu)
        {
            this.clu = clu;
        }

        @Override
        public void run()
        {
            if (isFinish) { return; }
            System.err.println("getting cluster result");
            VisClusteringInfo vci = null;
            try
            {
                vci = clu.getCurrentClusteringResultAsVisClusteringInfo();
            }
            catch (Exception e)
            {
                e.printStackTrace();
                // return;
            }
            JPanel panel = ClusteringGraph.createVisualizationViewer(vci,
                    new Dimension(400, 400));
            clusterPanel.removeAll();
            clusterPanel.add(panel);
            clusterPanel.updateUI();
        }
    }

    private JDialog getControlComponent()
    {
        if (controlComponent == null)
        {
            similarityLabel = new JLabel();
            // similarityLabel.setBounds(new Rectangle(540, 1, 100,
            // ComponentHeight)); // Generated
            similarityLabel.setHorizontalAlignment(SwingConstants.RIGHT); // Generated
            similarityLabel.setText("\u76f8\u4f3c\u5ea6\u7b97\u6cd5\uff1a"); // Generated
            clusterSizeLabel = new JLabel();
            clusterSizeLabel
                    .setText("\u6bcf\u6b21\u805a\u7c7b\u5927\u5c0f\uff1a"); // Generated
            clusterSizeLabel.setHorizontalAlignment(SwingConstants.RIGHT); // Generated
            clusterSizeLabel
                    .setToolTipText("\u5f53\u5230\u8fbe\u7684\u6587\u6863\u8fbe"
                            + "\u5230\u7ed9\u5b9a\u7684\u6570\u91cf\u65f6\u5f00"
                            + "\u59cb\u4e00\u6b21\u805a\u7c7b"); // Generated
            // clusterSizeLabel.setBounds(new Rectangle(270, 0, 100,
            // ComponentHeight)); // Generated
            ClusterCountLabel = new JLabel();
            ClusterCountLabel.setText("\u805a\u7c7b\u6570\uff1a"); // Generated
            ClusterCountLabel.setHorizontalAlignment(SwingConstants.RIGHT); // Generated
            // ClusterCountLabel.setBounds(new Rectangle(0, 1, 100,
            // ComponentHeight)); // Generated
            controlComponent = new JDialog();
            controlComponent.setTitle("XML流聚类属性设置");
            GridLayout layout = new GridLayout(4, 2, 30, 20);
            controlComponent.setLayout(layout); // Generated
            // controlDialog.setBounds(new Rectangle(0, 0, 200, 200)); //
            // Generated
            controlComponent.add(ClusterCountLabel, null); // Generated
            controlComponent.add(getClusterCountTextField(), null); // Generated
            controlComponent.add(clusterSizeLabel, null); // Generated
            controlComponent.add(getClusterSizeTextField(), null); // Generated
            controlComponent.add(similarityLabel, null); // Generated
            controlComponent.add(getSimilarityComboBox(), null); // Generated
            controlComponent.add(getStartButton(), null); // Generated
            controlComponent.add(getFinishButton(), null); // Generated
            controlComponent
                    .setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
            // controlComponent.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
            Dimension defaultSize = new Dimension(300, 200);
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            int x = (screenSize.width - defaultSize.width) / 2;
            int y = (screenSize.height - defaultSize.height) / 2;
            Point location = new Point(x, y);
            controlComponent.setSize(defaultSize);
            controlComponent.setResizable(false);
            controlComponent.setLocation(location);
        }
        return controlComponent;
    }

    /**
     * This method initializes ClusterCountTextField
     * 
     * @return javax.swing.JTextField
     */
    private JTextField getClusterCountTextField()
    {
        if (ClusterCountTextField == null)
        {
            ClusterCountTextField = new JTextField();
            // ClusterCountTextField.setBounds(new Rectangle(100, 1, 60,
            // ComponentHeight)); // Generated
        }
        return ClusterCountTextField;
    }

    /**
     * This method initializes clusterSizeTextField
     * 
     * @return javax.swing.JTextField
     */
    private JTextField getClusterSizeTextField()
    {
        if (blockSizeTextField == null)
        {
            blockSizeTextField = new JTextField();
            // blockSizeTextField.setBounds(new Rectangle(370, 1, 60,
            // ComponentHeight)); // Generated
            blockSizeTextField
                    .setToolTipText("\u5f53\u5230\u8fbe\u7684\u6587\u6863\u8fbe"
                            + "\u5230\u7ed9\u5b9a\u7684\u6570\u91cf\u65f6"
                            + "\u5f00\u59cb\u4e00\u6b21\u805a\u7c7b"); // Generated
        }
        return blockSizeTextField;
    }

    /**
     * This method initializes similarityComboBox
     * 
     * @return javax.swing.JComboBox
     */
    private JComboBox getSimilarityComboBox()
    {
        if (similarityComboBox == null)
        {
            similarityComboBox = new JComboBox();
            // similarityComboBox.setBounds(new Rectangle(640, 1, 120,
            // ComponentHeight)); // Generated
            // similarityComboBox.setFont(defaultFont); // Generated
            for (String str : similarityList)
            {
                similarityComboBox.addItem(str);
            }
        }
        return similarityComboBox;
    }

    /**
     * This method initializes finishButton
     * 
     * @return javax.swing.JButton
     */
    private JButton getFinishButton()
    {
        if (finishButton == null)
        {
            finishButton = new JButton();
            // finishButton
            // .setBounds(new Rectangle(450, 30, 100, ComponentHeight));
            finishButton.setText("\u7ed3\u675f");
            finishButton.addActionListener(new ActionListener()
            {
                @Override
                public void actionPerformed(ActionEvent e)
                {
                    isFinish = true;
                    setEnable(true);
                    startButton.setEnabled(true);
                    controlComponent.setVisible(false);
                }
            });
            finishButton.setEnabled(false);
        }
        return finishButton;
    }

    private void setEnable(boolean enabled)
    {
        blockSizeTextField.setEnabled(enabled);
        ClusterCountTextField.setEnabled(enabled);
        similarityComboBox.setEnabled(enabled);
    }

    /**
     * This method initializes startButton
     * 
     * @return javax.swing.JButton
     */
    private JButton getStartButton()
    {
        if (startButton == null)
        {
            startButton = new JButton();
            // startButton.setBounds(new Rectangle(250, 30, 100,
            // ComponentHeight)); // Generated
            startButton.setText("\u5f00\u59cb\u805a\u7c7b"); // Generated
            startButton.addActionListener(new ActionListener()
            {
                private CluVisualFrame parent;
                private String         ERROR = "\u9519\u8bef";

                public void actionPerformed(java.awt.event.ActionEvent e)
                {
                    if (blockSizeTextField.getText().isEmpty())
                    {
                        showErrorMessage("\u6bcf\u6b21\u805a\u7c7b\u5927\u5c0f"
                                + "\u4e0d\u80fd\u4e3a\u7a7a");
                        return;
                    }
                    if (ClusterCountTextField.getText().isEmpty())
                    {
                        showErrorMessage("\u805a\u7c7b\u6570\u4e0d\u80fd"
                                + "\u4e3a\u7a7a");
                        return;
                    }
                    if (similarityComboBox.getSelectedIndex() == -1)
                    {
                        showErrorMessage("\u5c1a\u672a\u9009\u62e9\u76f8\u4f3c"
                                + "\u5ea6\u7b97\u6cd5");
                    }
                    int clusterSize = -1, blocksize = -1;
                    try
                    {
                        clusterSize = new Integer(ClusterCountTextField
                                .getText());
                    }
                    catch (Exception e2)
                    {
                        showErrorMessage("\u805a\u7c7b\u6570\u5fc5\u987b\u662f"
                                + "\u4e00\u4e2a\u6574\u6570");
                        return;
                    }
                    try
                    {
                        blocksize = new Integer(blockSizeTextField.getText());
                    }
                    catch (Exception e2)
                    {
                        showErrorMessage("\u6bcf\u6b21\u805a\u7c7b\u5927\u5c0f"
                                + "\u5fc5\u987b\u662f\u4e00\u4e2a\u6574\u6570");
                        return;
                    }
                    new ResourceGetter(critical).start();
                    final StreammingKMedianClustering clu = new StreammingKMedianClustering(
                            blocksize, clusterSize, 2, similarityMap
                                    .get(similarityComboBox.getSelectedItem()),
                            critical);
                    new Thread()
                    {
                        @Override
                        public void run()
                        {
                            clu.run();
                        }
                    }.start();
                    parent.run(clu);
                    setEnable(false);
                    finishButton.setEnabled(true);
                    startButton.setEnabled(false);
                    controlComponent.setVisible(false);
                }

                private void showErrorMessage(String msg)
                {
                    showMessageDialog(parent, msg, ERROR, ERROR_MESSAGE);
                }

                public ActionListener setParent(CluVisualFrame parent)
                {
                    this.parent = parent;
                    return this;
                }
            }.setParent(this));
        }
        return startButton;
    }

    private class ResourceGetter extends Thread
    {
        private SAXReader                reader   = new SAXReader();
        private ResourceCritical<XMLDoc> resource = null;

        public ResourceGetter(ResourceCritical<XMLDoc> resource)
        {
            this.resource = resource;
        }

        @Override
        public void run()
        {
            int index = 0;
            byte[] xmlArray = null;
            String xmlName = null;
            Document doc = null;
            while (true)
            {
                if (!XmlTransfer.xmlNameList.isEmpty()
                        && !XmlTransfer.xmlList.isEmpty())
                {
                    String tmp = XmlTransfer.xmlNameList.get(0);
                    if (tmp.substring(0, tmp.length() - 4).equals(xmlName))
                    {
                        try
                        {
                            Thread.sleep(10);
                        }
                        catch (Exception e)
                        {}
                        continue;
                    }
                    xmlArray = XmlTransfer.xmlList.get(0);
                    xmlName = XmlTransfer.xmlNameList.get(0);
                    xmlName = xmlName.substring(0, xmlName.length() - 4);
                    ByteArrayInputStream in = new ByteArrayInputStream(xmlArray);
                    try
                    {
                        index++;
                        doc = reader.read(in);
                        // System.out.println("read doc:" + doc.getText());
                        XMLDoc xmlDoc = new XMLDoc(doc, xmlName);
                        System.out.println(index + ": push " + xmlDoc);
                        resource.push(xmlDoc);
                    }
                    catch (DocumentException e)
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * @return the critical
     */
    public ResourceCritical<XMLDoc> getCritical()
    {
        return critical;
    }

    /**
     * @param critical
     *            the critical to set
     */
    public void setCritical(ResourceCritical<XMLDoc> critical)
    {
        this.critical = critical;
    }

    /**
     * This method initializes clusterPane
     * 
     * @return javax.swing.JPanel
     */
    private JPanel getClusterPanel()
    {
        if (clusterPanel == null)
        {
            clusterPanel = new JPanel();
            clusterPanel.setLayout(new BorderLayout()); // Generated
            clusterPanel.setBounds(new Rectangle(0, 0, 600, 500)); // Generated
            clusterPanel.setBackground(Color.white);
        }
        return clusterPanel;
    }

    public static void main(String[] args) throws IOException
    {
        JFrame frame = new JFrame();
        frame.setSize(new Dimension(860, 760));
        CluVisualFrame cv = new CluVisualFrame();
        frame.setLayout(null);
        frame.add(cv);
        cv.setBounds(14, 20, 820, 730);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);

        final ResourceCritical<XMLDoc> resource = new ResourceCritical<XMLDoc>(
                1000);
        cv.setCritical(resource);
        cv.setVisible(true);

        XmlTransfer tran = new XmlTransfer(ROOT_PATH);
        tran.xmlControl();
    }
}
